/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package myconfession.utils;

import com.sun.codemodel.JCodeModel;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.sql.Timestamp;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 *
 * @author Liem
 */
public class XMLUtility {

    private XMLUtility() {
    }

    public static void generateJAXBClass(String xsdPath, String outputPackage,
            String outputFolder) throws IOException {
        SchemaCompiler sc = XJC.createSchemaCompiler();

        sc.setErrorListener(new ErrorListener() {

            public void error(SAXParseException saxpe) {
                System.err.println("Error: " + saxpe.getMessage());
            }

            public void fatalError(SAXParseException saxpe) {
                System.err.println("Fatal Error: " + saxpe.getMessage());
            }

            public void warning(SAXParseException saxpe) {
                System.err.println("Warning Error: " + saxpe.getMessage());
            }

            public void info(SAXParseException saxpe) {
                System.err.println("info Error: " + saxpe.getMessage());
            }
        });

        sc.forcePackageName(outputPackage);
        File schema = new File(xsdPath);
        InputSource is = new InputSource(schema.toURI().toString());
        sc.parseSchema(is);
        S2JJAXBModel model = sc.bind();
        JCodeModel code = model.generateCode(null, null);
        code.build(new File(outputFolder));
    }

    public static Object unmarshallJAXB(String xmlFilePath, Class unmarshallClass) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(unmarshallClass);
        Unmarshaller un = jc.createUnmarshaller();
        File file = new File(xmlFilePath);
        return un.unmarshal(file);
    }

    public static void marshallJAXB(String xmlFilePath, Object object) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(object.getClass());
        Marshaller mar = jc.createMarshaller();
        mar.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        File file = new File(xmlFilePath);
        mar.marshal(object, file);
    }

    public static void marshallJAXB(Writer wr, Object object) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(object.getClass());
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        marshaller.marshal(object, wr);
    }

    public static Document parseDOMfromFile(String filePath) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder builder = dbf.newDocumentBuilder();
        File f = new File(filePath);
        Document doc = builder.parse(f);
        return doc;
    }

    public static void writeDOMtoXml(Node node, String filePath) 
            throws TransformerConfigurationException, TransformerException, FileNotFoundException {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        Source source = new DOMSource(node);
        Result result = new StreamResult(new FileOutputStream(filePath));
        transformer.transform(source, result);

    }



    public static java.sql.Timestamp getSqlTimeStamp(XMLGregorianCalendar xgc) {
        if (xgc == null) {
            return null;
        } else {
            return new Timestamp(xgc.toGregorianCalendar().getTime().getTime());
        }
    }

    public static XMLGregorianCalendar getXMLGregorianCalendar(Timestamp timestamp) throws DatatypeConfigurationException {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeZone(TimeZone.getDefault());
        gc.setTimeInMillis(timestamp.getTime());
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    }
    public static XMLGregorianCalendar getXMLGregorianCalendarNow()
            throws DatatypeConfigurationException
    {
        GregorianCalendar gregorianCalendar = new GregorianCalendar();
        DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
        XMLGregorianCalendar now = 
            datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
        return now;
    }

    public static ByteArrayInputStream generatePDF(String xslFilePath, Source source) throws TransformerConfigurationException, TransformerException, FOPException, SAXException, IOException
    {
        Source xslSource = new StreamSource(new File(xslFilePath));
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer(xslSource);

        //Using data from the XML, transform the XSL into a FO source
        ByteArrayOutputStream foOutput = new ByteArrayOutputStream();
        Result foResult = new StreamResult(foOutput);
        transformer.transform(source, foResult);

        //Config the FOP factory to accept external UTF-8 fonts
        FopFactory fopFactory = FopFactory.newInstance();
        File config = new File(ConstantProvider.getInstance().getRootPath() + "WEB-INF/pdf/fop.xconf");
        fopFactory.setUserConfig(config);
        //Transform the FO content to PDF
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, outputStream);

        Transformer t2 = tf.newTransformer();
        ByteArrayInputStream foInput = new ByteArrayInputStream(foOutput.toByteArray());
        Source foSource = new StreamSource(foInput);
        Result pdf = new SAXResult(fop.getDefaultHandler());
        t2.transform(foSource, pdf);

        return new ByteArrayInputStream(outputStream.toByteArray());
    }

}
